package com.meshnetics.gb.type.impl.additional;

import com.meshnetics.gb.type.DataValue;
import com.meshnetics.gb.util.formatters.BufferFormatters;

import java.lang.reflect.Constructor;
import java.nio.ByteBuffer;

/**
 * Universal instantiable type.
 *
 * @author Yury Aserchev (yaserchev@meshnetics.com)
 *         Date: 27.08.2008 17:55:41
 */
public final class TypeInstantiable extends BaseDataType {
    private final Class instanceClass;
    private final Constructor constr;

    public TypeInstantiable(final String name, final Class instanceClass) {
        super(name);
        if (instanceClass == null) {
            throw new NullPointerException("parameter instanceClass is null");
        }
        this.instanceClass = instanceClass;
        try {
            constr = instanceClass.getConstructor(new Class[]{ByteBuffer.class});
        } catch (final NoSuchMethodException e) {
            final StringBuffer buff = new StringBuffer("class ").append(instanceClass.getName()).
                    append(" does not have public constructor with parameter of ByteBuffer type.");
            throw new IllegalArgumentException(buff.toString(), e);
        }
    }

    public DataValue deserialize(final ByteBuffer buffer) {
        try {
            return (DataValue) constr.newInstance(new Object[]{buffer});
        } catch (final Exception e) {
            final StringBuffer buff = new StringBuffer("Cannot create new instance of class ").
                    append(instanceClass.getName()).
                    append(" using constructor with parameter of ByteBuffer type and value '").
                    append(BufferFormatters.DEFAULT_ARRAY.format(buffer)).append("'.");
            throw new RuntimeException(buff.toString(), e);
        }
    }
}
